#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <algorithm>

using namespace std;

// 定义一个内存块结构体，包含起始位置、结束位置和标识符ID
struct Block {
    int start;
    int end;
    int id;

    // 用于排序Block按照start从小到大排列
    bool operator<(Block& other){
        return start < other.start;
    }
};

// 查找第一个可以容纳n字节的空闲区间索引
int findSuitableFreeBlock(vector<pair<int, int>>& free_blocks, int n) {
    for (size_t i = 0; i < free_blocks.size(); ++i) {
        int start = free_blocks[i].first;
        int end = free_blocks[i].second;
        if (end - start + 1 >= n) {
            return i; // 找到合适的空闲区间
        }
    }
    return -1; // 没有足够空间
}

// 分割空闲块，并插入新分配的内存块
void splitFreeBlock(vector<pair<int, int>>& free_blocks,
                    vector<Block>& memory_blocks,
                    int index, int n, int current_id) {
    int f_start = free_blocks[index].first;
    int f_end = free_blocks[index].second;
    int alloc_start = f_start;
    int alloc_end = f_start + n - 1;

    // 插入新分配的内存块
    memory_blocks.push_back({alloc_start, alloc_end, current_id});

    // 更新空闲区域：如果还有剩余空间，则更新；否则删除该空闲块
    if (alloc_end + 1 <= f_end) {
        free_blocks[index] = {alloc_end + 1, f_end};
    } else {
        free_blocks.erase(free_blocks.begin() + index);
    }
}

// 删除指定ID的内存块，成功返回true，失败返回false
bool eraseBlock(vector<Block>& memory_blocks,
                vector<pair<int, int>>& free_blocks, int x) {
    for (auto it = memory_blocks.begin(); it != memory_blocks.end(); ++it) {
        if ((*it).id == x) {
            int start = (*it).start;
            int end = (*it).end;
            memory_blocks.erase(it); // 删除对应内存块

            bool inserted = false;

            // 尝试合并相邻的空闲块
            for (size_t i = 0; i < free_blocks.size(); ++i) {
                int f_start = free_blocks[i].first;
                int f_end = free_blocks[i].second;

                // 当前空闲块在被删除块的前面（紧邻）
                if (f_end + 1 == start) {
                    free_blocks[i] = {f_start, end};
                    inserted = true;
                    break;
                }
                // 当前空闲块在被删除块的后面（紧邻）
                else if (end + 1 == f_start) {
                    free_blocks[i] = {start, f_end};
                    inserted = true;
                    break;
                }
            }

            // 如果没有相邻空闲块，就新增一个空闲区域
            if (!inserted) {
                free_blocks.push_back({start, end});
            }

            return true;
        }
    }
    return false;
}

// 内存碎片整理，将所有已分配块尽量靠前排列，保持原有顺序
void defragmentMemory(vector<Block>& memory_blocks,
                      vector<pair<int, int>>& free_blocks, int m) {
    // 先按起始地址排序
    sort(memory_blocks.begin(), memory_blocks.end());

    vector<Block> new_blocks;
    int current_pos = 0; // 当前可用起始位置

    // 将所有内存块移动到最前面
    for (auto& block : memory_blocks) {
        int size = block.end - block.start + 1;
        new_blocks.push_back({current_pos, current_pos + size - 1, block.id});
        current_pos = new_blocks.back().end + 1;
    }

    memory_blocks = new_blocks; // 替换为整理后的内存块列表

    // 清空原来的空闲区域，重新构建
    free_blocks.clear();
    int prev_end = -1;

    for (const auto& block : memory_blocks) {
        if (block.start > prev_end + 1) {
            // 添加中间的空闲区域
            free_blocks.push_back({prev_end + 1, block.start - 1});
        }
        prev_end = block.end;
    }

    // 添加最后的空闲区域（如果有）
    if (prev_end < m - 1) {
        free_blocks.push_back({prev_end + 1, m - 1});
    }
}

int main() {
    int t, m;
    cin >> t >> m;

    // 存储当前所有已分配的内存块
    vector<Block> memory_blocks;

    // 初始时整个内存都是空闲的
    vector<pair<int, int>> free_blocks = {{0, m - 1}};

    // 标识符从1开始递增
    int current_id = 1;

    cin.ignore(); // 忽略第一行输入后的换行符

    // 处理每个操作
    for (int _ = 0; _ < t; ++_) {
        string line;
        getline(cin, line); // 读取一行命令
        stringstream ss(line);
        string op;
        ss >> op;

        if (op == "alloc") {
            int n;
            ss >> n;

            // 查找合适的空闲区域
            int index = findSuitableFreeBlock(free_blocks, n);
            if (index != -1) {
                // 分配内存并输出ID
                splitFreeBlock(free_blocks, memory_blocks, index, n, current_id);
                cout << current_id << endl;
                current_id++;
            } 
			else {
                // 没有足够的连续空间
                cout << "NULL" << endl;
            }
        } 
		else if (op == "erase") {
            int x;
            ss >> x;

            // 删除指定ID的内存块
            if (!eraseBlock(memory_blocks, free_blocks, x)) {
                // ID不存在或无效
                cout << "ILLEGAL_ERASE_ARGUMENT" << endl;
            }
        } 
		else if (op == "defragment") {
            // 整理内存碎片
            defragmentMemory(memory_blocks, free_blocks, m);
        }
    }

    return 0;
}